package com.bjtu.restaurantreviews.service;

import com.bjtu.restaurantreviews.dao.*;
import com.bjtu.restaurantreviews.domain.*;
import com.bjtu.restaurantreviews.enums.ResultEnum;
import com.bjtu.restaurantreviews.exception.UserException;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.parameters.P;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpSession;
import javax.transaction.Transactional;
import java.io.BufferedOutputStream;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: Chen
 * @Description: 用户业务逻辑层
 * @Date: Created in 22:56 2018/4/4
 */
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private AdvertisementRepository advertisementRepository;

    @Autowired
    private TrackRepository trackRepository;

    @Autowired
    private RestaurantRepository restaurantRepository;
    @Autowired
    private ReviewRepository reviewRepository;
    @Autowired
    private PictureRepository pictureRepository;
    @Autowired
    private SparkresultRepository sparkresultRepository;

    @Autowired
    private EntityManager entityManager;

    //查询工厂实体
    private JPAQueryFactory queryFactory;

    //用户注册逻辑
    public void reg(String checkcode,User user, HttpSession session) throws Exception{

        if(!(userRepository.findByUphone(user.getUphone()).isEmpty())) {
            throw new UserException(ResultEnum.PHONE_USED);//手机号已注册
        }else if (!session.getAttribute("uphone").toString().equalsIgnoreCase(user.getUphone())){
            throw new UserException(ResultEnum.PHONE_WRONG);//手机号不对应
        }else if (verify(session,checkcode)){
            String encode = BCrypt.hashpw(user.getUpassword(),BCrypt.gensalt());
            user.setUpassword(encode);
            userRepository.save(user);//验证成功，进行注册
        }
    }
//        if(!(userRepository.findByUphone(user.getUphone()).isEmpty())){
//            throw new UserException(ResultEnum.PHONE_USED);//手机号已注册
//        }else if (randomNum==null || checkcode == null || !checkcode.equalsIgnoreCase(randomNum)){
//            throw new UserException(ResultEnum.SMS_WRONG);//验证码错误
//        }else if ((now.getTime()-codetime)/1000/60 > 5){
//            throw new UserException(ResultEnum.TIME_OUT);//验证码超时
//        }else {
//            String encode = BCrypt.hashpw(user.getUpassword(),BCrypt.gensalt());
//            user.setUpassword(encode);
//            userRepository.save(user);
//            session.removeAttribute("randomNum");//删除session中的数据
//            session.removeAttribute("codetime");
//        }

    //用户登录逻辑
//    public User userLogin(User user) throws Exception{
//        List<User> list = userRepository.findByUphoneAndUpassword(user.getUphone(),user.getUpassword());
//        if (userRepository.findByUphone(user.getUphone()).isEmpty()){
//            throw new UserException(ResultEnum.PHONE_UNREG);//手机号未注册
//        }else if (list.isEmpty()){
//            throw new UserException(ResultEnum.PWD_WRONG);//密码错误
//        }else {
//            User user1 = new User();
//            user1 = list.get(0);
//            user1.setUpassword(null);
//            return  user1;
//        }
//    }

    //用户登录逻辑
    public User userLogin(User user) throws Exception{
        List<User> list = userRepository.findByUphone(user.getUphone());

        if (list.isEmpty()) {
            throw new UserException(ResultEnum.PHONE_UNREG);//手机号未注册
        }else {
            User user1 = list.get(0);
            if (!(BCrypt.checkpw(user.getUpassword(),user1.getUpassword()))){
                throw new UserException(ResultEnum.PWD_WRONG);//密码错误
            }else {
                user1.setUpassword(null);
                user1.setUphone(null);
                return user1;
            }
        }
    }

    //验证码校验
    public Boolean verify(HttpSession session,String checkcode){
        Object orn = session.getAttribute("randomNum");//从session中获取已发送验证码
        if (orn ==null){
            throw new UserException(ResultEnum.SMS_WRONG);
        }
        String randomNum = orn.toString();
        Long codetime = Long.valueOf(session.getAttribute("codetime") + "");//从session中获取发送验证码时间
        Date now = new Date();

        if (randomNum==null || checkcode == null || !checkcode.equalsIgnoreCase(randomNum)){
            throw new UserException(ResultEnum.SMS_WRONG);//验证码错误
        }else if ((now.getTime()-codetime)/1000/60 > 5) {
            throw new UserException(ResultEnum.TIME_OUT);//验证码超时
        }else{
            session.removeAttribute("randomNum");//删除session中的数据
            session.removeAttribute("codetime");
            session.removeAttribute("uphone");
            return true;
        }
    }


    //重置密码
    @Transactional
    public void reset(String checkcode,User user, HttpSession session){
        if((userRepository.findByUphone(user.getUphone()).isEmpty())) {
            throw new UserException(ResultEnum.PHONE_UNREG);//手机号未注册
        }else if (!session.getAttribute("uphone").toString().equalsIgnoreCase(user.getUphone())){
            throw new UserException(ResultEnum.SMS_WRONG);//手机号不对应
        }else if (verify(session,checkcode)) {
            String encode = BCrypt.hashpw(user.getUpassword(), BCrypt.gensalt());
            userRepository.updatepwd(encode,user.getUphone());//更新密码
        }
    }

    //关键字模糊查询
    public HashMap inquire(String word,int pageNum) throws Exception{
        if (word == null){
            throw new UserException(ResultEnum.RESULT_ZERO);//字符串为空
        }
        int pageSize = 5;//每页数量
        int totalPages;//总页数
        long totalElements;//总条数
        Pageable pageable = new PageRequest(pageNum-1,pageSize);
//        ArrayList<Restaurant> list = restaurantRepository.findByWord(word);
        Page<Restaurant> page = restaurantRepository.findByWord(word,pageable);
        List<Restaurant> list = page.getContent();
        if (list.isEmpty()) {
            throw new UserException(ResultEnum.RESULT_ZERO);//没有找到符合条件的搜索结果
        }else {
            totalPages = page.getTotalPages();
            totalElements = page.getTotalElements();
            HashMap<String,Object> hashMap = new HashMap<>();
            hashMap.put("restaurants",list);
            hashMap.put("totalElements",totalElements);
            hashMap.put("totalPages",totalPages);
            return hashMap ;
        }
    }
//    //关键字模糊查询
//    public ArrayList<Restaurant> inquire(String word) throws Exception{
//        int pageNum = 1,pageSize = 5;
//        Pageable pageable = new PageRequest(pageNum,pageSize);
////        ArrayList<Restaurant> list = restaurantRepository.findByWord(word);
//        Page<Restaurant> page = restaurantRepository.findByWord(word,pageable);
//        List<Restaurant> list = page.getContent();
//        if (list.isEmpty()) {
//            throw new UserException(ResultEnum.RESULT_ZERO);//没有找到符合条件的搜索结果
//        }else {
//            return list ;
//        }
//    }

//    //过滤器查询
////    public List<Restaurant> filterquery(String type,String city,int pageNum) throws Exception{
////        int pageSize = 5;
////
////        Pageable pageable = new PageRequest(pageNum-1,pageSize);
////        Page<Restaurant> page = restaurantRepository.findAll(RestaurantSpec.getSpec(type,city),pageable);
////        List<Restaurant> list = page.getContent();
////        if (list.isEmpty()){
////            throw new UserException(ResultEnum.RESULT_ZERO);//没有找到符合条件的搜索结果
////        }else {
////            return list;
////        }
////    }

    //过滤器查询
    public HashMap filterquery(String type,String city,String word,String sort,int pageNum) throws Exception{
        int pageSize = 10;//每页数量
        int totalPages;//总页数
        long totalElements;//总条数
        Pageable pageable = new PageRequest(pageNum-1,pageSize);
        Page<Restaurant> page = restaurantRepository.findAll(RestaurantSpec.getSpec(type,city,word,sort),pageable);
        List<Restaurant> list = page.getContent();
        if (list.isEmpty()) {
            throw new UserException(ResultEnum.RESULT_ZERO);//没有找到符合条件的搜索结果
        }else {
            totalPages = page.getTotalPages();
            totalElements = page.getTotalElements();
            HashMap<String,Object> hashMap = new HashMap<>();
            hashMap.put("totalElements",totalElements);
            hashMap.put("restaurants",list);
            hashMap.put("totalPages",totalPages);
            return hashMap;
        }
    }

    //实例化控制器完成后执行该方法实例化JPAQueryFactory
    @PostConstruct
    public void initFactory() {
        System.out.println("开始实例化JPAQueryFactory");
        queryFactory = new JPAQueryFactory(entityManager);
    }

    //推荐餐馆逻辑
    public List<Restaurant> like(Integer tuid) {
        QTrack _Q_track = QTrack.track;
        QRestaurant _Q_restaurant = QRestaurant.restaurant;
        return
                queryFactory
                        .select(_Q_restaurant)
                        .from(_Q_restaurant,_Q_track)
                        .where(
                                _Q_track.trid.eq(_Q_restaurant.rid)
                                        .and(_Q_track.tuid.eq(tuid)))
                        .orderBy(_Q_track.tnum.desc())
                        .limit(4)
                        .fetch();
    }

    //查询轨迹信息
    public List<Track> query(Integer tuid, Integer trid) {
        QTrack _Q_track = QTrack.track;

        return queryFactory
                .selectFrom(_Q_track)
                .where(_Q_track.tuid.eq(tuid)
                        .and(_Q_track.trid.eq(trid)))
                .fetch();
    }

    //增加轨迹信息
    @Transactional
    public Track trackinsert(Integer tuid, Integer trid) {
        Track track = new Track();
            track.setTuid(tuid);
            track.setTrid(trid);
            track.setTnum(1);

        return trackRepository.save(track);
    }

    //更新轨迹信息
    @Transactional
    public void trackupdate(Integer tuid,Integer trid) {
        trackRepository.update(tuid,trid);
    }

    //餐馆详情推荐
    public List recommendtype(String rtype) {
        return restaurantRepository.recommendtype(rtype);
    }

    //广告餐馆
    public List advertisement() {
        return advertisementRepository.advertisement();
    }

    //用户详细信息
    public List userinfo(Integer uid) {
        return userRepository.userinfo(uid);
    }

    //推荐用户常去两种类型餐馆
    public HashMap selectType(Integer tuid) {
        QRestaurant _Q_restaurant = QRestaurant.restaurant;
        QTrack _Q_track = QTrack.track;
        List<Restaurant> list1 = queryFactory
                .select(_Q_restaurant)
                .from(_Q_restaurant, _Q_track)
                .where(_Q_restaurant.rid.eq(_Q_track.trid)
                        .and(_Q_track.tuid.eq(tuid)))
                .groupBy(_Q_restaurant.rtype)
                .orderBy(_Q_track.tnum.desc())
                .limit(2)
                .fetch();

        if (list1.isEmpty()) {
            throw new UserException(ResultEnum.RESULT_ZERO);//没有找到符合条件的搜索结果
        }else {
            HashMap<String,Object> hashMap1 = new HashMap<>();
            hashMap1.put("types",list1);

            String str1[] = list1.get(0).toString().replace(" ","").split(",");
            String str2[] = str1[9].split("'");
            String str3[] = list1.get(1).toString().replace(" ","").split(",");
            String str4[] = str3[9].split("'");

            List<Restaurant> list2 = queryFactory
                    .selectFrom(_Q_restaurant)
                    .where(_Q_restaurant.rtype.eq(str2[1]))
                    .orderBy(_Q_restaurant.rstar.desc(),_Q_restaurant.rservice.desc(),_Q_restaurant.rtaste.desc(),_Q_restaurant.renviro.desc())
                    .limit(6)
                    .fetch();

            List<Restaurant> list3 = queryFactory
                    .selectFrom(_Q_restaurant)
                    .where(_Q_restaurant.rtype.eq(str4[1]))
                    .orderBy(_Q_restaurant.rstar.desc(),_Q_restaurant.rservice.desc(),_Q_restaurant.rtaste.desc(),_Q_restaurant.renviro.desc())
                    .limit(6)
                    .fetch();

            list2.addAll(list3);
            HashMap<String,Object> hashMap2 = new HashMap<>();
            hashMap2.put("type1",str2[1]);
            hashMap2.put("type2",str4[1]);
            hashMap2.put("restaurants",list2);

            return hashMap2;
        }
    }

//    //显示餐馆评论详情
//    public HashMap detial(int rid,int pagenum){
//        int pagesize = 5;
//        int totalPages;//总页数
//        long totalElements;//总条数
//        HashMap<String,Object> hashMap = new HashMap<>();
//        Pageable pageable = new PageRequest(pagenum-1,pagesize);
//        Page<Review> page = reviewRepository.findByRevrid(rid,pageable);
//        List<Picture> listPicture = pictureRepository.findByPicrid(rid);
//        List<Review> listReview = page.getContent();
//        totalElements = page.getTotalElements();
//        totalPages = page.getTotalPages();
//        hashMap.put("reviews",listReview);
//        hashMap.put("pictures",listPicture);
//        hashMap.put("totalElements",totalElements);
//        hashMap.put("totalPages",totalPages);
//        return hashMap;
//    }

    //显示餐馆信息和图片
//    public HashMap RestaurantDetial(int rid){
//        HashMap<String,Object> hashMap = new HashMap<>();
//
//    }

    //用户查看自己评论
    public HashMap reviewinfo(Integer revuid,Integer pagenum) {
        int pagesize = 10;
        int totalPages;//总页数
        long totalElements;//总条数
        QReview _Q_review = QReview.review;
        HashMap<String,Object> hashMap = new HashMap<>();
        Pageable pageable = new PageRequest(pagenum-1,pagesize);
        Page<Review> page = reviewRepository.findByRevuid(revuid,pageable);
        List<Review> list = queryFactory
                .selectFrom(_Q_review)
                .where(_Q_review.revuid.eq(revuid))
                .orderBy(_Q_review.revtime.desc())
                .fetch();
        totalElements = page.getTotalElements();
        totalPages = page.getTotalPages();
        hashMap.put("reviews",list);
        hashMap.put("totalElements",totalElements);
        hashMap.put("totalPages",totalPages);
        return hashMap;
    }

    //查询根据Spark推荐结果
    public List sparkrecommend(int userid) throws Exception{
        List<Sparkresult> list = sparkresultRepository.findByUserid(userid);
        if (list.isEmpty()){
            throw new UserException(ResultEnum.USER_NONE);
        }else {
            Sparkresult sparkresult = list.get(0);
            List<Restaurant> list1 = new ArrayList<Restaurant>();
            list1.add(0,restaurantRepository.findByRid(sparkresult.getResult1()).get(0));
            list1.add(1,restaurantRepository.findByRid(sparkresult.getResult2()).get(0));
            list1.add(2,restaurantRepository.findByRid(sparkresult.getResult3()).get(0));
            list1.add(3,restaurantRepository.findByRid(sparkresult.getResult4()).get(0));
            return list1;
        }
    }

    //用户写评论
//    public void writereview(int revuid,int revrid,int revenviro,int revservice,int revtaste,float revscore,String revcontent) throws Exception{
////        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
////        String data1 = df.format(new Date());
////        Date date = df.parse(data1);
//        Review review = new Review();
//        review.setRevtime(new Date());
//        review.setRevrid(revrid);
//        review.setRevuid(revuid);
//        review.setRevenviro(revenviro);
//        review.setRevservice(revservice);
//        review.setRevtaste(revtaste);
//        review.setRevcontent(revcontent);
//        review.setRevscore(revscore);
//        System.out.println(review.toString());
//
//        reviewRepository.save(review);
//    }
    //写评论
    public void writereview(Review review)throws Exception{
        review.setRevtime(new Date());
        Integer revid = reviewRepository.findAll().size() + 1;
        review.setRevid(revid);
        review.setRevpicture("http://p0.meituan.net/mogu/62e02d8f5be6e9531e7b56417dc3442570507.jpg@380w_214h_1e_1c");
//        System.out.println(review.toString());
        System.out.println(revid);
        reviewRepository.save(review);
    }

    //显示餐馆评论
    public HashMap review(int rid,int pagenum,String sort){
        int pagesize = 10;
        int totalPages;//总页数
        long totalElements;//总条数
        HashMap<String,Object> hashMap = new HashMap<>();
        Pageable pageable = new PageRequest(pagenum-1,pagesize);
        if (sort.equalsIgnoreCase("默认排序")) {
            Page<Review> page = reviewRepository.findByRevrid(rid, pageable);
            List<Review> listReview = page.getContent();
            totalElements = page.getTotalElements();
            totalPages = page.getTotalPages();
            hashMap.put("reviews",listReview);
//        hashMap.put("pictures",listPicture);
            hashMap.put("totalElements",totalElements);
            hashMap.put("totalPages",totalPages);
        }else if (sort.equalsIgnoreCase("最新点评")){
            Page<Review> page = reviewRepository.findByRevridOrderByRevtimeDesc(rid,pageable);
            List<Review> listReview = page.getContent();
            totalElements = page.getTotalElements();
            totalPages = page.getTotalPages();
            hashMap.put("reviews",listReview);
//        hashMap.put("pictures",listPicture);
            hashMap.put("totalElements",totalElements);
            hashMap.put("totalPages",totalPages);
        }
//        List<Picture> listPicture = pictureRepository.findByPicrid(rid);
        return hashMap;
    }

    //餐馆详细信息
    public HashMap restaurantinfo(Integer rid) {
        QRestaurant _Q_restaurant = QRestaurant.restaurant;
        QPicture _Q_picture = QPicture.picture;
        HashMap<String,Object> hashMap = new HashMap<>();
        List<Restaurant> list = queryFactory
                .selectFrom(_Q_restaurant)
                .where(_Q_restaurant.rid.eq(rid))
                .fetch();
        List<PictureDTO> listPicture = queryFactory
                .select(
                        Projections.bean(
                                PictureDTO.class,
                                _Q_picture.picpicture
                        )
                )
                .from(_Q_picture)
                .where(_Q_picture.picrid.eq(rid))
                .fetch();
        Restaurant restaurant = list.get(0);
        hashMap.put("Restaurant",restaurant);
        hashMap.put("Pictures",listPicture);
        return hashMap;
    }

    //用户昵称及头像
    public List cmt_uinfo(String cuid[]) {
        QUser _Q_user = QUser.user;
        List<UserDTO> list = new ArrayList<>();
        List<UserDTO> list2 = new ArrayList<>();
        int[] str = new int[cuid.length];
        for(int i = 0;i < cuid.length;i++) {
            str[i] = Integer.parseInt(cuid[i]);
        }
        for (int j = 0;j<str.length;j++) {
            list = queryFactory
                    .select(
                            Projections.bean(
                                    UserDTO.class,
                                    _Q_user.uname,
                                    _Q_user.uphoto
                            )
                    )
                    .from(_Q_user)
                    .where(_Q_user.uid.eq(str[j]))
                    .fetch();
            list2.addAll(list);
        }
        return list2;
    }
}